{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "很多时候我们在项目开发中所使用的数据是并不规整的，我们需要对原数据进行数据清洗。而排序则是数据清洗中必不可少的一道环节。刚好作为一门快速开发的语言，Python 中的数据排序方式也是非常好用的。这道题可以使用 Python 中的内置函数 sorted()。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**答案**\n",
    "使用Python内置排序函数sorted\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{201902: '小红', 201901: '小明', 201903: '小强'}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d = {201901:\"小明\",201902:\"小红\",201903:\"小强\"}\n",
    "dict(sorted(d.items(), key=lambda x: x[1])) # 降序\n",
    "dict(sorted(d.items(), key=lambda x: x[1], reverse=True)) # 升序\n",
    "#Tips: 注意在Python3.6之后，字典的顺序会保持插入时的顺序，所以按上面的答案写是没有问题的。\n",
    "#但是Python3.6之前的版本没有这个特性，如果你对sorted()返回的一个不可变的有序元组对象再执行一次dict类型转换，\n",
    "#Python会给出一个不一样的结果。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "考虑是否需要返回dict对象。如果不需要，那最简单了，sorted(d.items(), key=lambda x: x[1])直接返回一个由元组组成的有序列表。\n",
    "如果需要返回dict，就看Python版本了。如果是在Python3.6之后，直接类型强转，也没有问题；如果是在Python3.6之前，可能需要考虑用OrderedDict。\n",
    "如果你能在真正的面试中，能够以这样的思路回答问题，面试官是很高兴的，一是因为你考虑问题周全，二，也间接地说明你对Python的特性非常了解。\n",
    "\n",
    "**拓展：Python的常用排序方案**  \n",
    "Python的常用排序方案：有两种 sort() 函数和sorted() 函数。\n",
    "\n",
    "**列表方法list.sort()修改列表本身**。  \n",
    "sort(*, key=None, reverse=False)，两个可选参数，key指定带有单个参数的函数，用于从列表的每个元素中提取用于比较的键。reverse为一个布尔值。如果设为True，则每个列表元素将按反向顺序比较进行排序。\n",
    "\n",
    "Tips: 注意使用列表排序方法的时候，它是直接作用于列表本身，不会返回一个新的列表。\n",
    "\n",
    "内置函数sorted()可以从一个迭代对象构建返回一个新的排序列表。sorted(iterable, *, key=None, reverse=False)，同样，也有两个可选参数。但是，这里的key函数是从任意可迭代对象iterable的每个元素中提取用于比较的键。reverse的用法一样。\n",
    "\n",
    "Tips: key一般都使用匿名函数或者内置函数\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 5]\n",
      "['Bob', 'Mark', 'David', 'Daniel']\n"
     ]
    }
   ],
   "source": [
    "a = [3,2,5,1]\n",
    "a.sort() # 打印a，输出为[1, 2, 3, 5]\n",
    "print (a)\n",
    "names = ['Mark', 'Bob', 'Daniel', 'David']\n",
    "names.sort(key=len) # 打印names，按字符串长度排序，输出为['Bob', 'Mark', 'David', 'Daniel']\n",
    "print (names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**加分点**  \n",
    "这道题你在回答的时候需要考虑下题目是否需要返回一个dict对象，如果不需要的话那最简单了：sorted(d.items(), key=lambda x: x[1])直接返回一个由元组组成的有序列表。\n",
    "\n",
    "但是如果需要返回一个 dict 对象，那就要看你的 Python 版本了，如果是在 Python3.6 之后，直接类型强转，也没有问题；如果是在 Python3.6 之前，可能需要考虑用OrderedDict。\n",
    "\n",
    "如果在真正的面试中你能够考虑到这一点，那么你会给面试官一种：”这小子可以啊“的感觉。一是因为你考虑问题比较周全，二也间接说明你对 Python 的特性非常的了解。\n",
    "\n",
    "面试官追问：s = \"ajldjlajfdljfddd\"，去重并从小到大排序输出\"adfjl\"\n",
    "这个问题就比较有意思了，它同时涉及了前面两道题中的去重和排序。我们可以这样做：直接将字符串 s 强制转为集合达到去重的目的，然后在强转为列表，使用sort() 方法进行排序，最后使用join()方法将排好序的列表拼接起来即可，如果你掌握了前两道题中的知识点，这道题可以说是非常的简单。\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'adfjl'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = \"ajldjlajfdljfddd\"\n",
    "s = list(set(s)) # 第一步，去重\n",
    "s.sort() # 第二步，排序\n",
    "\"\".join(s) # 第三步，拼接\n",
    "\n",
    "#这道题可能有多种解法，如果你有不同或者更好的方式欢迎在评论区与我交流哈。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}